use strict;
use warnings;

package JasPerl::CGI;

use CGI;
use JasPerl::PageConfig;

use JasPerl::CGI::Request;
use JasPerl::CGI::Response;

use Module::Load;

my $jsp_package = 'Local::JSP';

sub get_module_name {
    my $path = shift;
    my @pseg = map {
        s/(\W|_)+/_/g;
        length($_) ? ($_) : ()
    } split('/', $path);
    unshift @pseg, $jsp_package if $jsp_package;
    return join('::', @pseg);
}

sub new {
    my ($class, %param) = @_;
    my $cgi = delete $param{cgi} || CGI->new;

    bless { cgi => $cgi, attributes => { } }, $class;
}

sub dispatch {
    my ($self, $path, $attrs) = @_;
    my $request = $self->get_request($attrs);
    my $response = $self->get_response();

    my $modname = get_module_name($path);

    # TODO: compile and load class, caching
    load $modname;

    my $page = $modname->new;
    $page->init(JasPerl::PageConfig->new($modname, $self, { 'test' => 42} ));

    $self->{cgi}->header();
    return $page->service($request, $response);
}

sub get_request {
    my ($self, $attrs) = @_;
    return JasPerl::CGI::Request->new($self->{cgi}, $attrs);
}

sub get_response {
    my ($self) = @_;
    return JasPerl::CGI::Response->new($self->{cgi});
}

sub get_attribute_names {
    return JasPerl::Util::Enumeration->from_list(keys %{$_[0]->{attributes}});
}

sub get_attribute {
    return $_[0]->{attributes}->{$_[1]};
}

sub set_attribute {
    if (defined $_[2]) {
        $_[0]->{attributes}->{$_[1]} = $_[2];
    } else {
        delete $_[0]->{attributes}->{$_[1]};
    }
}

sub remove_attribute {
    delete $_[0]->{attributes}->{$_[1]};
}

sub get_request_dispatcher {
    return JasPerl::RequestDispatcher->new($_[0]->{config}, $_[1]);
}

1;
